home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 38
/
Amiga Format CD38 (1999-03-15)(Future Publishing)(GB)(Track 1 of 3)[!][issue 1999-04].iso
/
-in_the_mag-
/
reader_requests
/
dice_v3.15
/
doc
/
dmake.doc
< prev
next >
Wrap
Text File
|
1999-01-26
|
9KB
|
240 lines
DMAKE V 2.0
Matthew Dillon dillon@Overload.Berkeley.CA.US
891 Regal Rd. uunet.uu.net!overload!dillon
Berkeley, Ca. 94708
USA
DMake - Dillon's MAKE utility (NOT Make or Lmk compatible.. better)
The idea with DMake is to provide a powerful make utility through
general features rather than specialized hacks. DMake is governed
by a few simple rules that can be combined into incredibly powerful
operations.
Generally you simply run 'DMake' and have a list of dependancies in
your 'DMakefile' which DMake then executes. The DMakefile may contain
three different kinds of lines:
(1) COMMENTS -- Any line beginning with a '#' is a comment and ignored
# This DMakefile generates an executable for fubar, the compiler
# options are as follows ...
(2) ASSIGNMENTS -- Any line of the form <SYMBOL> = ... is considered
an assignment. Any variable references from within the assignment will
be resolved immediately.
CFLAGS= -r
SRCS= x.c y.c z.c
(3) DEPENDANCIES: -- A line containing a list of symbols, a colon, and
more symbols is assumed to be a dependancy. Note that you cannot
have a raw filename with a colon in it as that confuses DMake.
Instead, use an ASSIGNMENT variable.
Following the dependancy line is zero or more command lines --
commands to run to resolve the dependancy, terminated with a
blank line.
NOTE: not only is a zero-command dependancy allowed, it is necessary in
some cases. A particular destination may have only ONE command list so
if you have something like 'a.o : a.c' with a command list to compile
the source into an object you can also have another dependancy such as
'a.o : defs.h' which would NOT have any associated command list.
dst1 ... dstN : src1 ... srcN
command1
command2 ...
dst1 ... dstN : src1 ... srcN
command1
command2 ...
Finally, note that a dst* or src* symbol does not need to be a
filename. It is perfectly valid to make up dummy names which are then
used as the lhs of a dependancy that collects other dependancies
together.
DEPENDANCIES
When declaring dependancies you may use four different forms. The
first form is to have a single destination and several sources. This
is intreted to mean that ALL the sources must be resolved before the
single destination can be resolved via the command list for the
dependancy. The special variable, %(left), is set to the <dst> symbol
and the special variable %(right) is set to ALL of the <src*> symbols
For example, this form would be used to indicate that an executable
depends on all the objects being resolved before you can run the link.
(1) dst : src1 src2 src3 ... srcN
The second form is the most useful in that it allows you to specify
multiple 1 : 1 dependancies. Thus, you can specify, for example, that
each object file depends on its source file counterpart for ALL the
files in your project on a single line and have a single command list
representing what to do (to compile a source file into an object, say).
In this case %(left) and %(right) are set to each dst* : src* pair
individually and the command list is run for any individual pair that
is out of date.
(2) dst1 dst2 dst3 ... dstN : src1 src2 src3 ... srcN
The next form may be used to specify that many files depend on one file
being resolved. An example of usage would be to make all the object
files depend on one header file. The command list, if any, is run for
each dst* : src pair with %(left) set to the current dst* and %(right)
set to the single source.
(3) dst1 dst2 dst3 ... dstN : src
The last form is esoteric but sometimes useful. EACH dst* on the left
hand side depends on the entire right hand side. You can have an
arbitrary number of symbols on either side. %(left) will be set to a
particular DST while %(right) will be set to all of the SRCs.
for example, you could specify $(OBJS) :: $(HDRS) -- make all objects
depend on all headers causing a recompile to occur if any header is
modified.
(4) dst1 dst2 dst3 ... dstN :: src1 src2 ... srcI
WILDCARDED FILE LIST REPLACEMENT
VARIABLE ACCESS
DMake's most powerful feature is an easy to use file list replacement
through options in a variable specification. You may insert the
contents of any variable using the form:
$(SYMBOL)
Furthermore, you can make modifications to the contents of the variable
on the fly using:
$(SYMBOL:wildcard) only those files which match <wildcard>
$(SYMBOL:wildcard:wildcard) matching files and also do a conversion
Simple */? wildcarding is used. A wildcard may contain a colon or
other punctuation but if it does you MUST surround it with quotes. Here
is a quick example:
SRCS= a.c b.c c.c d.c xx.a
OBJS= $(SRCS:*.c:"dtmp:%1.o")
all:
echo $(OBJS)
(the result is 'dtmp:a.o dtmp:b.o dtmp:c.o dtmp:d.o')
The first wildcard specification restricts which files from the list
are to be taken -- 'xx.a' was ignored, as you can see. Each '*' or '?'
in the first wildcard specification corresponds to %N specifications
in the second wildcard specification. You can prepend, insert, or
append text and freely mix or ignore items matched to create your
destination file list.
This capability allows you to specify your source files EXACTLY ONCE
in the DMakefile and then use the file munging capability to convert
them to the object file list, etc...
You can embed variables within variables as with the following example
(note that this time xx.a is included):
OD= dtmp:fubar/
SRCS= a.c b.c c.c d.c xx.a
OBJS= $(SRCS:*.?:"$(OD)%1.o")
all:
echo $(OBJS)
(the result is: 'dtmp:fubar/a.o dtmp:fubar/b.o dtmp:fubar/c.o
dtmp:fubar/d.o dtmp:fubar/xx.o')
As a side note, you may also specify '?' and '*' in the destination
wildcard. These are considered dummies and are equivalent to %N where
N is incremented from 1..9 for each '?' or '*' encountered.
You can use the capability anywhere in the DMakefile. Another common
thing to do is restrict your link line to include only the object files
and skip the headers:
$(EXE) : $(PROTOS) $(OBJS) $(HDRS)
dcc %(right:*.o) -o %(left)
ENVIROMENT VARIABLES
2.0 local variables and 1.3/2.0 ENV: variables are fully accessible.
Under 2.0 you can also modify local variables on the fly.
DMake-specific variables override 2.0 local variables overide ENV:
variables.
Under 2.0, any command containing '<', '>', '`', or '|', or is an
alias, will be run with System(). Thus, such commands may not be used
to modify local variables or the local enviroment. Also, such commands
cannot be ^C'd due to the way AmigaDOS works.
LINE CONTINUATION AND ESCAPES
Any line may be continued by terminating it with a backslash '\'. It
is possible to escape the special characters '$' and '%' by doubling
them though this is only necessary if an open-parenthesis follows the
'$' or '%' and you do not want it interpreted as a variable.
It is possible to escape ':' and other special characters by assigning
them (or a string containing them) to a variable
COMMAND SHELL
Under 2.0 commands that do not contain any sort of redirection are run
with RunCommand(). If a command is an alias or there is some sort of
redirection in the arguments it will be run with System().
Under 1.3 everything is run with Execute()
EXTREMELY ADVANCED CAPABILITIES
Now, you may have noted earlier that I said you could not have any
givem left-hand-side with more then one command list. Take, for
example:
a.o : a.c
dcc %(right) -o %(left)
a.o : defs.h
**** illegal to put command list here ****
Actually, it isn't illegal. When DMake encounters a dependancy without
a command list it will automatically 'force' the next higher level
dependancy of the same left-hand-side. Therefore if you do not have a
command list for the lower level left-hand-side things work as you
expect. Note that this requires all such null dependancies to exist
AFTER the one that has the command list.
If you do have two or more command lists for the same left-hand-side
they will run independant of each other according to their individual
right hand sides. If several command lists apply then their order of
execution will be bottom-up
EXISTANCE OF A FILE OR DIRECTORY
Another advanced feature quite useful in fully automating the
compilation process is the ability to create a directory tree on
the fly. That is, if you have a projects called 'fubar' and want
the objects to go into the directory DTMP:fubar/ you might want to
have a dependancy that creates DTMP:fubar if it does not already
exist.
XX= dtmp:fubar
$(XX) : $(XX)
makedir %(left)